package tables

import (
	"net"
	"ospf/common"
	"sync"
	"time"
)

const RouterDeadInterval = 40

type Neighbor struct {
	routerId common.ID
	// 与目标ip相连的网卡
	inf    *net.Interface
	ip     common.ID
	deadAt int64
	status common.NeiStat
}

func (n *Neighbor) GetStatus() common.NeiStat {
	return n.status
}

func (n *Neighbor) GetRouterId() common.ID {
	return n.routerId
}

func (n *Neighbor) GetIP() common.ID {
	return n.ip
}

type NeighborTable struct {
	t  map[common.ID]*Neighbor
	mu sync.Mutex
}

// Update 更新邻居信息
func (nt *NeighborTable) Update(routerId common.ID, inf *net.Interface, ip common.ID, stat uint8) {
	nt.mu.Lock()
	nt.t[routerId] = &Neighbor{
		routerId: routerId,
		inf:      inf,
		ip:       ip,
		deadAt:   time.Now().Unix() + int64(RouterDeadInterval),
		status:   common.NeiStat(stat),
	}
	nt.mu.Unlock()
}

// Prune 清除过期的邻居消息
func (nt *NeighborTable) Prune() {
	nt.mu.Lock()
	defer nt.mu.Unlock()
	for id, neighbor := range nt.t {
		if time.Now().Unix() > neighbor.deadAt {
			delete(nt.t, id)
		}
	}
}

// GetNeighbors 返回当前邻居表
func (nt *NeighborTable) GetNeighbors() []Neighbor {
	nei := make([]Neighbor, 0, len(nt.t))
	nt.mu.Lock()
	for _, e := range nt.t {
		nei = append(nei, *e)
	}
	nt.mu.Unlock()
	return nei
}

// Find returns Neighbor by router-id
func (nt *NeighborTable) Find(id common.ID) *Neighbor {
	nt.mu.Lock()
	defer nt.mu.Unlock()
	return nt.t[id]
}

// GetNeighborsSimple 返回当前邻居表
func (nt *NeighborTable) GetNeighborsSimple() []common.ID {
	ids := make([]common.ID, 0, len(nt.t))
	nt.mu.Lock()
	for id := range nt.t {
		ids = append(ids, id)
	}
	nt.mu.Unlock()
	return ids
}
